<?php
/**
 * coreModelCacheDriverMemcache
 *
 * 데이터 베이스 캐시 - 멤캐시 드라이버
 *
 * @package core
 * @author  Platform Team
 */

class coreModelCacheDriverMemcache extends coreModelCacheDriverCommon
{
    /**
     * Memcache 객체
     * @var Memcache
     */
    private $Memcache;

    /**
     * 캐시 드라이버 구동
     *
     * @param array $aConfig
     */
    public function open($aConfig)
    {
        $sHost = $aConfig['MemcacheHost'];
        $sPort = $aConfig['MemcachePort'];

        $Memcache = new Memcache();

        $isConnect = $Memcache->connect($sHost, $sPort);

        if ($isConnect === false) {

            throw new Exception('[Database Cache Driver] can not connect to memcache driver - ' . $sHost . ':' . $sPort);

        }

        $this->Memcache = $Memcache;
    }

    /**
     * 캐시 드라이버 종료
     */
    public function close()
    {
        $this->Memcache->close();
    }

    /**
     * 캐시 데이터 읽기
     *
     * @param string $sNsp
     * @param string $sKey
     * @return array(
     *  'identity' => 캐시 파일 경로 혹은 캐시 키(드라이버에 따라 다름)
     *  'itime' => 초기 생성 시간
     *  'expire' => 만료 시간
     *  'data' => 대상 데이터
     * ) | false
     */
    public function read($sNsp, $sKey)
    {
        $sNsp = $this->getNamespace($sNsp);
        $sNspSeqKey = $this->_nspSeqKey($sNsp);
        $sNspSeq = $this->Memcache->get($sNspSeqKey);

        if ($sNspSeq === false) {
            return false;
        }

        $sDataKey = $this->_dataKey($sNspSeqKey, $sNspSeq, $sKey);

        $aGenerateData = $this->Memcache->get($sDataKey);

        if ($this->isValid($aGenerateData) === true) {
            $aGenerateData['identity'] = $sDataKey;
            return $aGenerateData;
        }

        return false;
    }

    /**
     * 캐시 데이터 생성
     *
     * @param string $sNsp
     * @param string $sKey
     * @param mixed $mValue
     * @return boolean
     */
    public function write($sNsp, $sKey, $mValue, $iExpire)
    {
        if ($mValue === false) return false;

        $sNsp = $this->getNamespace($sNsp);
        $sNspSeqKey = $this->_nspSeqKey($sNsp);
        $sNspSeq = $this->Memcache->get($sNspSeqKey);

        if ($sNspSeq === false) {
            $sNspSeq = 1;
            $this->Memcache->set($sNspSeqKey, $sNspSeq, false);
        }

        $sDataKey = $this->_dataKey($sNspSeqKey, $sNspSeq, $sKey);

        $aGenerateData = $this->generateData($mValue, $iExpire);

        return $this->Memcache->set($sDataKey, $aGenerateData, false);
    }

    /**
     * 캐시 데이터 만료
     *
     * @param string $sNsp
     * @return boolean
     */
    public function expire($sNsp)
    {
        $sNsp = $this->getNamespace($sNsp);
        $sNspSeqKey = $this->_nspSeqKey($sNsp);
        $sNspSeq = $this->Memcache->get($sNspSeqKey);

        if ($sNspSeq === false) {
            return false;
        }

        $sNspSeq = $sNspSeq + 1;
        return $this->Memcache->set($sNspSeqKey, $sNspSeq, false);
    }

    /**
     * 네임스페이스 시퀀스 키 반환
     *
     * @param string $sNsp
     * @return string
     */
    private function _nspSeqKey($sNsp)
    {
        $sNspSeqKey = $this->sUid . $sNsp;

        return $sNspSeqKey;
    }

    /**
     * 데이터 키 반환
     *
     * @param string $sNspSeqKey
     * @param string $sNspSeq
     * @param string $sKey
     * @return string
     */
    private function _dataKey($sNspSeqKey, $sNspSeq, $sKey)
    {
        return md5($sNspSeqKey . $sNspSeq . $sKey);
    }
}